import React from 'react';

export default () => {
  // 1. 数字的和基于字符串的枚举
  {
    enum Direction {
      Up ,
      Down,
      Left,
      Right
    }
    function respond(recipient: string, message: Direction): void {
      console.log(recipient + ' ' + message)
    }
    respond("Princess Caroline", Direction.Up);

    enum Direction2 {
      Up = "UP",
      Down = "DOWN",
      Left = "LEFT",
      Right = "RIGHT",
    }
  }

  // 2. 常量枚举表达式
  {
    enum FileAccess {
      // constant members
      None,
      Read    = 1 << 1,
      Write   = 1 << 2,
      ReadWrite  = Read | Write,
      // computed member
      G = "123".length
    }
  }

  // 3. 使用枚举成员做类型
  {
    enum ShapeKind {
      Circle,
      Square,
    }

    interface Circle {
      kind: ShapeKind.Circle;
      radius: number;
    }

    interface Square {
      kind: ShapeKind.Square;
      sideLength: number;
    }

    let c: Circle = {
      kind: ShapeKind.Square, // Error!
      radius: 100,
    }
  }

  // 4. 枚举类型比较值被发现的低级错误
  {
    enum E {
      Foo,
      Bar,
    }

    function f(x: E) {
      if (x !== E.Foo || x !== E.Bar) {
        // Error! 检查没有通过，那么 x则 只能为 E.Foo，因此没理由再去检查它是否为 E.Bar
      }
    }
  }
  // 5. 枚举在运行时，是真正存在的对象，不同于 string 等这种类型
  {
    enum E {
      X, Y, Z
    }

    function f(obj: { X: number }) {
      return obj.X;
    }

    console.log(f(E));
  }
  // 6. 数字枚举反向映射
  {
    enum Enum {
      A
    }
    let a = Enum.A;
    let nameOfA = Enum[a]; // "A"
  }
  // 7. 常量枚举
  {
    // const enum Directions {
    //   Up,
    //   Down,
    //   Left,
    //   Right
    // }
    //
    // let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right]
  }
  return (
    <div>
      <h1>枚举</h1>
      <p>1. TypeScript支持数字的和基于字符串的枚举。数字枚举会从0自增长，字符串枚举没有，可以很好的序列化。</p>
      <p>2. 枚举第一个成员没初始化，会赋予值 0。常量枚举表达式，可以在编译阶段求值，满足条件如下。</p>
      <ul>
        <li>一个枚举表达式字面量（主要是字符串字面量或数字字面量）</li>
        <li>一个对之前定义的常量枚举成员的引用（可以是在不同的枚举类型中定义的）</li>
        <li>带括号的常量枚举表达式</li>
        <li>一元运算符 +, -, ~ 其中之一应用在了常量枚举表达式</li>
        <li>常量枚举表达式做为二元运算符 +, -, *, /, %, &lt;&lt;, >>, >>>, &, |, ^ 的操作对象。 若常数枚举表达式求值后为 NaN或 Infinity，则会在编译阶段报错。</li>
      </ul>
      <p>3. 字面量枚举成员指不带有初始值的常量枚举成员，或者值初始化为：任何字符串字面量、数字字面量、使用了一元字符的数字字面量。枚举成员就成为了类型。</p>
      <p>4. 枚举类型本身变成了每个枚举成员的联合，类型系统知道枚举里的值的集合。 因此，TypeScript能够捕获在比较值的时候犯的愚蠢的错误。</p>
      <p>5. 枚举在运行时，是真正存在的对象，不同于 string 等这种类型。</p>
      <p>6. 数字枚举反向映射， 从枚举值到枚举名字。</p>
      <p>7. const枚举，常量枚举只能使用常量枚举表达式。但是测试有的不支持常量枚举。</p>
      <p>7. 外部枚举。在正常的枚举里，没有初始化方法的成员被当成常数成员。 对于非常数的外部枚举而言，没有初始化方法时被当做需要经过计算的。</p>
    </div>
  );
}
// 7. 外部枚举
declare enum Enum {
  A = 1,
  B,
  C = 2
}
